package com.thales.sentinel;

import Aladdin.Hasp;
import Aladdin.HaspStatus;
import org.springframework.stereotype.Service;

/**
 * Sentinel LDK Licensing Service
 * 提供密钥登录和读取只读内存的服务
 */
@Service
public class LdkLicensingService {
    // 供应商代码 - 这是示例代码，实际应用中应使用您的供应商代码
    public static final String VENDOR_CODE = new String(
            "AzIceaqfA1hX5wS+M8cGnYh5ceevUnOZIzJBbXFD6dgf3tBkb9cvUF/Tkd/iKu2fsg9wAysYKw7RMA" +
                    "sVvIp4KcXle/v1RaXrLVnNBJ2H2DmrbUMOZbQUFXe698qmJsqNpLXRA367xpZ54i8kC5DTXwDhfxWT" +
                    "OZrBrh5sRKHcoVLumztIQjgWh37AzmSd1bLOfUGI0xjAL9zJWO3fRaeB0NS2KlmoKaVT5Y04zZEc06" +
                    "waU2r6AU2Dc4uipJqJmObqKM+tfNKAS0rZr5IudRiC7pUwnmtaHRe5fgSI8M7yvypvm+13Wm4Gwd4V" +
                    "nYiZvSxf8ImN3ZOG9wEzfyMIlH2+rKPUVHI+igsqla0Wd9m7ZUR9vFotj1uYV0OzG7hX0+huN2E/Id" +
                    "gLDjbiapj1e2fKHrMmGFaIvI6xzzJIQJF9GiRZ7+0jNFLKSyzX/K3JAyFrIPObfwM+y+zAgE1sWcZ1" +
                    "YnuBhICyRHBhaJDKIZL8MywrEfB2yF+R3k9wFG1oN48gSLyfrfEKuB/qgNp+BeTruWUk0AwRE9XVMU" +
                    "uRbjpxa4YA67SKunFEgFGgUfHBeHJTivvUl0u4Dki1UKAT973P+nXy2O0u239If/kRpNUVhMg8kpk7" +
                    "s8i6Arp7l/705/bLCx4kN5hHHSXIqkiG9tHdeNV8VYo5+72hgaCx3/uVoVLmtvxbOIvo120uTJbuLV" +
                    "TvT8KtsOlb3DxwUrwLzaEMoAQAFk6Q9bNipHxfkRQER4kR7IYTMzSoW5mxh3H9O8Ge5BqVeYMEW36q" +
                    "9wnOYfxOLNw6yQMf8f9sJN4KhZty02xm707S7VEfJJ1KNq7b5pP/3RjE0IKtB2gE6vAPRvRLzEohu0" +
                    "m7q1aUp8wAvSiqjZy7FLaTtLEApXYvLvz6PEJdj4TegCZugj7c8bIOEqLXmloZ6EgVnjQ7/ttys7VF" +
                    "ITB3mazzFiyQuKf4J6+b/a/Y");

    // 本地范围定义
    private static final String LOCAL_SCOPE = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" +
            "<haspscope>" +
            "    <license_manager hostname=\"localhost\" />" +
            "</haspscope>";

    // 不使用认证运行时的配置
    private static final String NOT_USE_AUTH_RUNTIME_CONFIG = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" +
            "<haspformat root=\"config\">" +
            "    <feature>" +
            "        <auth_runtime>" +
            "            <mode>disabled</mode>" +
            "        </auth_runtime>" +
            "    </feature>" +
            "</haspformat>";

    // 演示数据缓冲区大小
    private static final int DEMO_MEMBUFFER_SIZE = 2048;

    /**
     * 执行密钥登录和读取操作
     * @param featureId 功能ID
     * @return 操作结果信息
     */
    public String performLicenseOperation(int featureId) {
        StringBuilder result = new StringBuilder();
        result.append("Sentinel LDK Licensing Service - 登录密钥和读取只读内存\n");
        result.append("Copyright (C) THALES. All rights reserved.\n\n");

        Hasp hasp = new Hasp(featureId);

        // 配置不使用认证运行时
        // hasp.config(NOT_USE_AUTH_RUNTIME_CONFIG, VENDOR_CODE);
        int status = hasp.getLastError();

        // if (status != HaspStatus.HASP_STATUS_OK) {
        //     System.out.println("配置失败，错误码: " + status);
        //     return;
        // }

        // 登录到密钥
        result.append("登录到密钥... ");
        hasp.login(VENDOR_CODE);
        status = hasp.getLastError();

        switch (status) {
            case HaspStatus.HASP_STATUS_OK:
                result.append("成功\n");
                break;
            case HaspStatus.HASP_FEATURE_NOT_FOUND:
                result.append("未找到Sentinel密钥\n");
                return result.toString();
            case HaspStatus.HASP_HASP_NOT_FOUND:
                result.append("未找到Sentinel密钥\n");
                return result.toString();
            case HaspStatus.HASP_OLD_DRIVER:
                result.append("驱动版本过旧或未安装驱动\n");
                return result.toString();
            case HaspStatus.HASP_NO_DRIVER:
                result.append("未找到Sentinel密钥\n");
                return result.toString();
            case HaspStatus.HASP_INV_VCODE:
                result.append("无效的供应商代码\n");
                return result.toString();
            default:
                result.append("登录失败，错误码: " + status + "\n");
                return result.toString();
        }

        // 获取会话信息
        result.append("\n获取会话信息...\n");
        String info = hasp.getSessionInfo(Hasp.HASP_KEYINFO);
        status = hasp.getLastError();

        if (status == HaspStatus.HASP_STATUS_OK) {
            result.append("密钥信息:\n===============\n").append(info).append("\n===============\n\n");
        } else {
            result.append("获取会话信息失败，错误码: ").append(status).append("\n");
        }

        // 读取只读内存
        result.append("\n获取只读内存大小...\n");
        int fileSize = hasp.getSize(Hasp.HASP_FILEID_RO);
        status = hasp.getLastError();

        if (status == HaspStatus.HASP_STATUS_OK) {
            result.append("只读内存大小: ").append(fileSize).append(" 字节\n");

            // 限制演示中使用的内存大小
            if (fileSize > DEMO_MEMBUFFER_SIZE) {
                fileSize = DEMO_MEMBUFFER_SIZE;
            }

            // 读取内存
            result.append("\n读取 ").append(fileSize).append(" 字节的只读内存...\n");
            byte[] memBuffer = new byte[DEMO_MEMBUFFER_SIZE];

            hasp.read(Hasp.HASP_FILEID_RO, 0, memBuffer);
            status = hasp.getLastError();

            if (status == HaspStatus.HASP_STATUS_OK) {
                result.append("读取成功\n");
                //找到第一个null字符的位置
                int endIndex = memBuffer.length;
                for (int i = 0; i < memBuffer.length; i++) {
                    if (memBuffer[i] == 0) {
                        endIndex = i;
                        break;
                    }
                }
                String content = new String(memBuffer, 0, endIndex).trim();
                result.append("内存内容:\n===============\n").append(content).append("\n===============\n\n");
            } else {
                result.append("读取内存失败，错误码: ").append(status).append("\n");
            }
        } else {
            result.append("获取内存大小失败，错误码: ").append(status).append("\n");
        }

        // 登出
        result.append("\n登出... ");
        hasp.logout();
        status = hasp.getLastError();

        if (status == HaspStatus.HASP_STATUS_OK) {
            result.append("成功\n");
        } else {
            result.append("失败，错误码: ").append(status).append("\n");
        }
        
        return result.toString();
    }

    /**
     * 以十六进制格式显示内存内容
     * 
     * @param buffer 内存缓冲区
     * @param size   要显示的字节数
     * @return 格式化的十六进制字符串
     */
    public String dumpMemory(byte[] buffer, int size) {
        StringBuilder result = new StringBuilder();
        StringBuilder hexData = new StringBuilder();
        StringBuilder asciiData = new StringBuilder();
        
        result.append("偏移量  十六进制数据                                    ASCII\n");
        result.append("------  ----------------------------------------  ----------------\n");
        
        for (int i = 0; i < size; i++) {
            // 每行开始显示偏移量
            if (i % 16 == 0) {
                if (i > 0) {
                    result.append(String.format("%06X  %-40s  %s\n", i - 16, hexData.toString(), asciiData.toString()));
                    hexData.setLength(0);
                    asciiData.setLength(0);
                }
            }
            
            // 添加十六进制值
            hexData.append(String.format("%02X ", buffer[i] & 0xFF));
            
            // 添加ASCII值（如果可打印）
            if (buffer[i] >= 32 && buffer[i] <= 126) {
                asciiData.append((char) buffer[i]);
            } else {
                asciiData.append('.');
            }
        }
        
        // 添加最后一行
        int lastLineOffset = size - (size % 16 == 0 ? 16 : size % 16);
        result.append(String.format("%06X  %-40s  %s\n", lastLineOffset, hexData.toString(), asciiData.toString()));
        
        return result.toString();
    }
}